package org.demo.test.springbatch;

import com.hundsun.jrescloud.batch.api.BatchJobExplorer;
import com.hundsun.jrescloud.batch.runtime.springbatch.factory.ExecutorProxyFactoryBean;
import com.hundsun.jrescloud.batch.runtime.springbatch.job.*;
import com.hundsun.jrescloud.batch.runtime.springbatch.step.BatchStepBuilder;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.integration.partition.MessageChannelPartitionHandler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.batch.BatchDatabaseInitializer;
import org.springframework.boot.autoconfigure.batch.BatchProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * 批处理配置
 *
 */
@EnableBatchProcessing
@Configuration
@EnableConfigurationProperties(BatchProperties.class)
public class BatchAutoConfig {

    private final BatchProperties properties;

    public BatchAutoConfig(BatchProperties properties) {
        this.properties = properties;
    }

    /**
     * 执行器代理包装类
     */
    @Bean
    public ExecutorProxyFactoryBean executorProxyFactoryBean(BatchStepBuilder stepBuilder) {
        return new ExecutorProxyFactoryBean(stepBuilder);
    }

    /**
     * Job 元信息存储
     */
    @Bean
    public BatchJobRepository batchJobRepository(@Qualifier("batchDataSource") DataSource dataSource, @Qualifier("batchTransactionManager") DataSourceTransactionManager transactionManager) throws Exception {
        return new BatchJobRepository(dataSource, transactionManager);
    }

    /**
     * Job 工厂
     */
    @Bean
    public BatchJobFactory batchJobFactory(BatchJobBuilder jobBuilder,
                                           BatchStepBuilder stepBuilder,
                                           @Qualifier("masterPartitionHandler") MessageChannelPartitionHandler partitionHandler,
                                           BatchJobRegistry batchJobRegistry
    ) {
        return new BatchJobFactory(jobBuilder, stepBuilder, partitionHandler, batchJobRegistry);
    }

    /**
     * Job 启动器(异步)
     */
    @Bean("asyncBatchJobLauncher")
    public AsyncBatchJobLauncher asyncBatchJobLauncher(BatchJobFactory batchJobFactory, BatchJobRepository batchJobRepository) {
        AsyncBatchJobLauncher batchJobLauncher = new AsyncBatchJobLauncher();
        batchJobLauncher.setBatchJobFactory(batchJobFactory);
        batchJobLauncher.setBatchJobRepository(batchJobRepository);
        return batchJobLauncher;
    }

    /**
     * Job 启动器(同步)
     */
    @Bean("syncBatchJobLauncher")
    public SyncBatchJobLauncher syncBatchJobLauncher(BatchJobFactory batchJobFactory, BatchJobRepository batchJobRepository) {
        SyncBatchJobLauncher batchJobLauncher = new SyncBatchJobLauncher();
        batchJobLauncher.setBatchJobFactory(batchJobFactory);
        batchJobLauncher.setBatchJobRepository(batchJobRepository);
        return batchJobLauncher;
    }

    /**
     * Job 构建器
     */
    @Bean
    public BatchJobBuilder batchJobBuilder(BatchJobRepository repository) {
        return new BatchJobBuilder(repository.getJobBuilderFactory());
    }

    /**
     * Step 构建器
     */
    @Bean
    public BatchStepBuilder batchStepBuilder(BatchJobRepository repository) {
        return new BatchStepBuilder(repository.getStepBuilderFactory());
    }

    /**
     * Job 注册器
     */
    @Bean
    public BatchJobRegistry batchJobRegistry(BatchJobRepository repository) {
        return new BatchJobRegistry(repository.getJobRegistry());
    }

    @Bean
    public SimpleBatchJobOperator simpleBatchJobOperator(BatchJobRepository batchJobRepository, BatchJobFactory batchJobFactory) {
        SimpleBatchJobOperator simpleBatchJobOperator = new SimpleBatchJobOperator();
        simpleBatchJobOperator.setJobExplorer(batchJobRepository.getJobExplorer());
        simpleBatchJobOperator.setJobLauncher(batchJobRepository.getAsyncJobLauncher());
        simpleBatchJobOperator.setJobRepository(batchJobRepository.getJobRepository());
        simpleBatchJobOperator.setBatchJobFactory(batchJobFactory);
        return simpleBatchJobOperator;
    }

    @Bean
    public BatchJobExplorer simpleBatchJobExplorer(BatchJobRepository batchJobRepository) {
        SimpleBatchJobExplorer simpleBatchJobOperator = new SimpleBatchJobExplorer();
        simpleBatchJobOperator.setJobExplorer(batchJobRepository.getJobExplorer());
        return simpleBatchJobOperator;
    }

    @Bean
    public BatchDatabaseInitializer batchDatabaseInitializer(@Qualifier("batchDataSource") DataSource dataSource,
                                                             ResourceLoader resourceLoader) {
        return new BatchDatabaseInitializer(dataSource, resourceLoader, this.properties);
    }
}
